package com.rui.heiMa.sort;

/**
 * @author : [锐神NO.3]
 * @version : [v1.0]
 * @className : Merge
 * @createTime : [2022/2/15 17:00]
 * @description : [归并排序]
 */

@SuppressWarnings("all")
public class Merge {

    private static Comparable[] assist;

    /**
     * 对数组a中的㢝进行排序
     */
    public static void sort(Comparable[] a){
        //1.初始化辅助数组assist
        assist = new Comparable[a.length];

        //2.定义一个lo变量，和hi变量，记录数组中最小的索引和最大的索引
        int lo = 0;
        int hi = a.length - 1;

        //3.调用sort重载方法，完成数组a中从索引lo到hi的元素的排序
        sort(a, lo, hi);
    }

    /**
     * 对数组a中从lo到hi的元素进行排序
     */
    private static void sort(Comparable[] a, int lo, int hi){
        //做安全性校验
        if(lo >= hi){
            return;
        }

        //对数据lo到hi之间的数据进行分组
        int mid = lo + (hi - lo) / 2;

        //分完组之后分别对每一组数据排序
        sort(a, lo, mid);
        sort(a, mid + 1, hi);
        //再把两个组中的数据进行归并
        merge(a, lo, mid, hi);
    }

    /**
     * 对数组中，从lo到mid为一组，从mid+1到hi为一组进行归并
     */
    private static void merge(Comparable[] a, int lo, int mid, int hi){
        //定义三个指针
        int i = lo;
        int p1 = lo;
        int p2 = mid + 1;

        //遍历，移动p1指针和p2指针，找出小的那个，把它放到assist数组中，放入之后指针后移
        while(p1 <= mid && p2 <= hi){
            //比较索引处的值
            if(less(a[p1], a[p2])){
                assist[i] = a[p1];
                i++;
                p1++;
            }else {
                assist[i] = a[p2];
                i++;
                p2++;
            }
        }

        //遍历，如果p1的指针没有走完，那么顺序移动p1指针，把对应的元素放到辅助数组的对应索引位置处
        while(p1 <= mid){
            assist[i] = a[p1];
            i++;
            p1++;
        }

        //遍历，如果p2的指针没有走完，那么顺序移动p2指针，把对应的元素放到辅助数组的对应索引位置处
        while(p2 <= hi){
            assist[i] = a[p2];
            i++;
            p2++;
        }
        //把辅助数组中的元素拷贝到原数组中
        for(int j = lo; j <= hi; j++){
            a[j] = assist[j];
        }
    }

    /**
     * 比较v元素是否小于w元素
     */
    private static boolean less(Comparable v, Comparable w){
        return v.compareTo(w) < 0;
    }

    /**
     * 数组元素i和j交换位置
     */
    private static void exch(Comparable[] a, int i, int j){
        Comparable temp;
        temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }
}
